import { CanvasCtrl } from "./CanvasCtrl";
import { TriCir } from "./TriCir";

export class CanvasTriCir extends TriCir<CanvasCtrl> {
  constructor(w: number, h: number) {
    super(w, h, CanvasCtrl)
  }

  protected lw: number = 1;
  pointerdown(x: number, y: number) {
    for (const ctrl of this.ctrls.toReversed()) {
      if (ctrl.hover) {
        ctrl.pointerdown(x, y);
        break;
      }
    }
  }

  pointermove(x: number, y: number) {
    const list = this.ctrls.toReversed();
    const c = list.find(v => v.pressed || v.hover);
    if (c) {
      c.pointermove(x, y);
    } else {
      for (const ctrl of list) {
        ctrl.pointermove(x, y);
        if (ctrl.hover) break;
      }
    }
  }

  pointerup(x: number, y: number) {
    for (const ctrl of this.ctrls)
      ctrl.pressed && ctrl.pointerup(x, y);
  }

  draw_dot = (ctx: CanvasRenderingContext2D, x: number, y: number, name?: string) => {
    const black = '#00000088';
    const white = '#AAAAAAFF';
    ctx.setLineDash([]);
    if (name) {
      ctx.strokeStyle = 'white';
      ctx.fillStyle = 'black';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.lineWidth = 3;
      ctx.strokeText(name, x, y);
      ctx.fillText(name, x, y);
    } else {
      ctx.lineWidth = 1;
      ctx.strokeStyle = black;
      ctx.fillStyle = white;
      ctx.beginPath();
      ctx.ellipse(x, y, 4, 4, 0, 0, Math.PI * 2);
      ctx.fill();
      ctx.stroke();
    }
  };

  render(ctx: CanvasRenderingContext2D) {
    const { o, r } = this;
    ctx.lineJoin = 'round';
    ctx.lineCap = 'round';
    ctx.lineWidth = this.lw;
    ctx.fillStyle = 'white';
    ctx.strokeStyle = '#00000088';
    ctx.setLineDash([this.lw * 2]);
    ctx.beginPath();
    ctx.ellipse(o.x, o.y, r, r, 0, 0, Math.PI * 2);
    ctx.stroke();

    ctx.textAlign = 'left';
    ctx.textBaseline = 'top';
    ctx.fillStyle = 'black';
    ctx.strokeStyle = 'white';
    let y = 0;
    for (const situation of this.situations) {
      const m = ctx.measureText(situation);
      y += m.actualBoundingBoxAscent + m.actualBoundingBoxDescent + 10;
      ctx.strokeText(situation, 0, y);
      ctx.fillText(situation, 0, y);
    }
    y = 0;
    const cur_situations = ['current:', ...this.cur_situations()];
    for (const situation of cur_situations) {
      const m = ctx.measureText(situation);
      y += m.actualBoundingBoxAscent + m.actualBoundingBoxDescent + 10;
      ctx.strokeText(situation, this.w - 200, y);
      ctx.fillText(situation, this.w - 200, y);
    }
    ctx.beginPath();
    this.shadow_dots.forEach(({ x, y }, i) => ctx[i ? 'lineTo' : 'moveTo'](x, y));
    ctx.closePath();

    ctx.fillStyle = '#00000022';
    ctx.strokeStyle = '#000000';
    ctx.fill();

    this.shadow_dots.forEach(({ x, y, name }) => this.draw_dot(ctx, x, y, name));
    const cross_dots = this.cross_dots();

    ctx.beginPath();
    cross_dots.forEach(({ x, y }, i) => ctx[i ? 'lineTo' : 'moveTo'](x, y));
    ctx.closePath();

    ctx.fillStyle = '#00000022';
    ctx.strokeStyle = '#000000';
    ctx.fill();

    cross_dots.forEach(({ x, y, name }) => this.draw_dot(ctx, x, y, name));

    this.ctrls.forEach(c => this.draw_dot(ctx, c.watch.x, c.watch.y));
    this.ctrls.forEach(c => c.render(ctx));
  }
}
